package com.foxnicweb.app.patent.job;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foxnicweb.app.constants.enums.patent.MemberType;
import com.foxnicweb.app.constants.enums.patent.PatentProcessStatus;
import com.foxnicweb.app.domain.patent.Patent;
import com.foxnicweb.app.domain.patent.PatentMember;
import com.foxnicweb.app.domain.patent.PatentProcess;
import com.foxnicweb.app.domain.patent.UserMapping;
import com.foxnicweb.app.patent.service.IPatentMemberService;
import com.foxnicweb.app.patent.service.IPatentProcessService;
import com.foxnicweb.app.patent.service.IPatentService;
import com.foxnicweb.app.patent.service.IUserMappingService;
import com.github.foxnic.api.error.ErrorDesc;
import com.github.foxnic.api.transter.Result;
import com.github.foxnic.commons.busi.id.IDGenerator;
import com.github.foxnic.commons.collection.CollectorUtil;
import com.github.foxnic.commons.concurrent.task.SimpleTaskManager;
import com.github.foxnic.commons.lang.DataParser;
import com.github.foxnic.commons.lang.DateUtil;
import com.github.foxnic.commons.lang.StringUtil;
import com.github.foxnic.commons.log.Logger;
import com.github.foxnic.dao.data.Rcd;
import com.github.foxnic.dao.data.RcdSet;
import com.github.foxnic.dao.data.SaveMode;
import com.github.foxnic.dao.meta.DBColumnMeta;
import com.github.foxnic.dao.meta.DBTableMeta;
import com.github.foxnic.sql.expr.Update;
import com.github.foxnic.sql.meta.DBDataType;
import com.github.foxnic.sql.parameter.BatchParamBuilder;
import com.mysql.jdbc.log.Log;
import io.swagger.models.auth.In;
import org.github.foxnic.web.constants.enums.bpm.RemindStatus;
import org.github.foxnic.web.constants.enums.bpm.RemindTermUnit;
import org.github.foxnic.web.constants.enums.dict.EmployeeStatus;
import org.github.foxnic.web.constants.enums.dict.OrgNodeType;
import org.github.foxnic.web.constants.enums.system.UnifiedUserType;
import org.github.foxnic.web.domain.bpm.*;
import org.github.foxnic.web.domain.changes.DataUnit;
import org.github.foxnic.web.domain.hrm.*;
import org.github.foxnic.web.domain.job.Job;
import org.github.foxnic.web.domain.oauth.Role;
import org.github.foxnic.web.domain.oauth.RoleVO;
import org.github.foxnic.web.domain.oauth.User;
import org.github.foxnic.web.domain.oauth.UserVO;
import org.github.foxnic.web.domain.system.*;
import org.github.foxnic.web.framework.bpm.BpmAssistant;
import org.github.foxnic.web.framework.bpm.ProcessDelegate;
import org.github.foxnic.web.framework.cluster.ClusterToken;
import org.github.foxnic.web.framework.proxy.ProxyContext;
import org.github.foxnic.web.proxy.hrm.EmployeeServiceProxy;
import org.github.foxnic.web.proxy.hrm.OrganizationServiceProxy;
import org.github.foxnic.web.proxy.hrm.PositionServiceProxy;
import org.github.foxnic.web.proxy.oauth.RoleServiceProxy;
import org.github.foxnic.web.proxy.oauth.UserServiceProxy;
import org.github.foxnic.web.proxy.system.BusiRoleMemberServiceProxy;
import org.github.foxnic.web.proxy.system.BusiRoleServiceProxy;
import org.github.foxnic.web.proxy.system.UserTenantServiceProxy;
import org.github.foxnic.web.proxy.utils.SystemConfigProxyUtil;
import org.github.foxnic.web.session.SessionUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;


/**
 * 专利案件数据同步
 * */
@Component
public class PatentDataSyncExecutor extends BaseJobExecutor {


    public static final String PROCESS_DEFINITION_CODE = "patent_process";
    @Autowired
    private IPatentService patentService;

    @Autowired
    private IPatentProcessService patentProcessService;

    @Autowired
    private IPatentMemberService patentMemberService;



    @Override
    public String getName() {
        return "专利案件同步";
    }

    @Override
    public Result execute(Object context, Job job, JSONObject methodParams) {

        this.initIf();

        // 立即处理细节
        SimpleTaskManager.doParallelTask(new Runnable() {
            @Override
            public void run() {
                try {
                    syncPatentsDetail();
                } catch (Exception e) {
                    Logger.exception(e);
                }
            }
        });

        //  同步专利案件数据
        try {
            Date date= DateUtil.addDays(new Date(),-365);
            List<Long> ids=patentService.dao().query("select id from "+patentService.table()).getValueList("id",Long.class);
            this.syncPatents(ids,1,date);
        } catch (Exception e) {
            Logger.exception(e);
            return ErrorDesc.exception(e);
        }


        return ErrorDesc.success();
    }


    /**
     * 同步组织数据
     * */
    private void syncPatents(List<Long> ids,int page,Date date) {
        Map<String,String> params=new HashMap<>();
        params.put("page",page+"");
        params.put("listRows","500");
        // params.put("query[]","{\"creation_time\":\""+ DateUtil.format(date,"yyyy-MM-dd") +"|\"}");
        // 1已立案 0未立案 2暂存
        // params.put("status","0");
        JSONObject data=this.get("/patents",params,"patents");
        if(data==null) return;
        Integer lastPage=data.getInteger("last_page");
        JSONArray array=data.getJSONArray("data");
        BatchParamBuilder batchParamBuilder=new BatchParamBuilder();
        for (int i = 0; i < array.size(); i++) {
            JSONObject itm=array.getJSONObject(i);
            Long id=itm.getLong("id");
            if(ids.contains(id)) continue;

            batchParamBuilder.add(id,itm.getString("serial"),itm.getString("title"),itm.getInteger("status"),itm.getDate("creation_time"));

            if(batchParamBuilder.size()>=100) {
                patentService.dao().batchExecute("insert into "+patentService.table()+" (id,serial,title,status,creation_time) values(?,?,?,?,?)",batchParamBuilder.getBatchList());
                batchParamBuilder.clear();
            }
        }
        //
        if(batchParamBuilder.size()>0) {
            patentService.dao().batchExecute("insert into " + patentService.table() + "(id,serial,title,status,creation_time) values(?,?,?,?,?)", batchParamBuilder.getBatchList());
            batchParamBuilder.clear();
        }

        System.err.println("\n\n== PAGE "+page+"/"+lastPage+" ================\n\n");

        if(lastPage>page) {
            syncPatents(ids,page+1,date);
        } else {
            this.syncPatentsDetail();
        }

    }

    private static Map<String,String> EMP_BADGE_CACHE=new HashMap<>();

    private void syncPatentsDetail() {

        User user=BpmAssistant.getUserByAccount(CALLER_ACCOUNT);
        ClusterToken token=new ClusterToken();
        token.setTenantId(user.getActivatedTenant().getOwnerTenantId());
        token.setAccount(user.getAccount());
        ProxyContext.initCallee(token);
        ProxyContext.setCallerAccount(CALLER_ACCOUNT);

        // 读取配置，生成基础的提醒信息
        List<ProcessInstanceRemindVO> reminds=new ArrayList<>();
        RemindTermUnit remindTermUnit=RemindTermUnit.parseByCode(SystemConfigProxyUtil.getString("patent.remindTermUnit"));
        List<Config> nodeConfigs = SystemConfigProxyUtil.queryDescendants("patent.process");
        for (Config nodeConfig : nodeConfigs) {
            String nodeCode=StringUtil.getLastPart(nodeConfig.getCode(),".");
            Integer term=DataParser.parseInteger(SystemConfigProxyUtil.getString(nodeConfig.getCode()+".term"));
            String remindEmployeeBadgeStr=SystemConfigProxyUtil.getString(nodeConfig.getCode()+".remindEmployeeBadges");
            String[] badges=remindEmployeeBadgeStr.split(",");
            List<String> empIds=new ArrayList<>();
            for (String badge : badges) {
                String empId=EMP_BADGE_CACHE.get(badge);
                if(empId!=null) {
                    empIds.add(empId);
                } else if ("".equals(empId)) {
                    // 人员不存在
                    continue;
                } else {
                    EmployeeVO employeeVO = new EmployeeVO();
                    employeeVO.setBadge(badge);
                    Result<List<Employee>> result = EmployeeServiceProxy.api().queryList(employeeVO);
                    if (result.success() && result.data() != null && !result.data().isEmpty()) {
                        empId = result.data().get(0).getId();
                        empIds.add(empId);
                    } else {
                        empId="";
                    }
                    EMP_BADGE_CACHE.put(badge,empId);
                }
            }



            ProcessInstanceRemindVO remind=new ProcessInstanceRemindVO();
            remind.setContent("审批超期提醒:"+nodeConfig.getName());
            remind.setStatusEnum(RemindStatus.pending);
            remind.setRemindTermUnitEnum(remindTermUnit);
            remind.setRemindTerm(term);
            remind.setTargetNodeId(nodeCode);
            remind.setReceiverInfo(StringUtil.join(empIds,","));
            reminds.add(remind);
        }



       RcdSet rs=patentService.dao().query("select id,subtype,title,customer from "+patentService.table()+" a where status=0 and not exists (select 1 from pat_patent_process b where a.id=b.id)");
        for (Rcd r : rs) {
            try {
                Long id=r.getLong("id");
                JSONObject data = r.toJSONObject();
                if(r.getValue("subtype")==null) {
                    data=this.syncDetail(id, reminds);
                }
                if(data!=null) {
                    // 启动审批流程
                    startProcessIf(id, data.getString("title"), data.getString("subtype"), data.getString("customer"), reminds);
                }
            } catch (Exception e) {
                Logger.exception(e);
            }
        }
    }

    private JSONObject syncDetail(Long id,List<ProcessInstanceRemindVO> reminds) {
        // 填充必要的明细信息
        Map<String,String> params=new HashMap<>();

        JSONObject data = this.get("/patents/"+id,params,"patent");
        if(data==null)  return null;
        DBTableMeta tm=patentService.dao().getTableMeta(patentService.table());
        Update update=new Update(patentService.table());
        for (String field : data.keySet()) {
            DBColumnMeta cm=tm.getColumn(field);
            if(cm==null) continue;
            if(cm.isPK()) continue;
            Object value=cm.read(data);
            update.set(field, value);
        }
        update.set("status", 0);
        update.where("id=?",id);
        patentService.dao().execute(update);

        List<String> fields=new ArrayList<>();
        fields.add("id");
        for (MemberType value : MemberType.values()) {
            fields.add(value.name());
        }

        // 保存项目成员信息
        Rcd patent=patentService.dao().queryRecord("select "+ StringUtil.join(fields,",") +" from "+patentService.table()+" where id=?",id);
        patentService.dao().execute("delete from "+patentMemberService.table()+" where patent_id=?",id);
        for (MemberType type : MemberType.values()) {
            String str=patent.getString(type.name());
            if(StringUtil.isBlank(str)) continue;
            str=str.trim();
            JSONArray array = new JSONArray();
            if(str.startsWith("[") && str.endsWith("]")) {
                array.addAll(JSONArray.parseArray(str));
            } else if(str.startsWith("{") && str.endsWith("}")) {
                array.add(JSONObject.parse(str));
            }

            for (int i = 0; i < array.size(); i++) {
                JSONObject itm=array.getJSONObject(i);
                PatentMember member=PatentMember.create();
                member.setPatentId(id);
                member.setEmpId(itm.getString("id"));
                member.setMemberType(type.name());
                member.setName(itm.getString("name"));
                patentMemberService.save(member, SaveMode.NOT_NULL_FIELDS);
            }
        }


        return data;


    }

    private synchronized void startProcessIf(Long id,String title,String subtype,String customer,List<ProcessInstanceRemindVO> reminds) {

        PatentProcess patentProcess = patentProcessService.getById(id);
        if(patentProcess!=null && patentProcess.getStatus()!=null) {
            return;
        }

        JSONObject subTypeJson=JSONObject.parseObject(subtype);
        JSONObject customerJson=JSONObject.parseObject(customer);

        if(patentProcess==null) {
            patentProcess=PatentProcess.create();
        }
        patentProcess.setId(id);
        patentProcess.setSubtype(subTypeJson.getString("id"));
        patentProcess.setCustomerName(customerJson.getString("name"));
        patentProcessService.insert(patentProcess);

        ProcessDelegate delegate=ProcessDelegate.createFromProcessDefinition(PROCESS_DEFINITION_CODE,CALLER_ACCOUNT);
        Result<ProcessInstance> result = delegate.temporarySave(title,id.toString());
        if(result.failure()) {
            throw new RuntimeException(result.message());
        }



        result=delegate.start();
        if(result.failure()) {
            throw new RuntimeException(result.message());
        }
        String processInstanceId=result.data().getId();
        patentProcess.setProcessInstanceId(processInstanceId);
        patentProcess.setStatus(PatentProcessStatus.A01.code());
        // patentProcess.setTenantId("T001");
        patentProcessService.updateDirtyFields(patentProcess);

        // 查询流程节点
        for (ProcessInstanceRemindVO remind : reminds) {
            remind=remind.clone();
            ProcessDefinitionNode node= delegate.getNodeByCamundaNodeId(remind.getTargetNodeId());
            remind.setTargetNodeId(node.getId());
        }
        // 设置审批提醒
        delegate.addReminds(reminds);

        System.out.println("OK");
    }


}
